/*
 *  Created on: Jun 5, 2009
 *      Author: Ramesh Rajaby
 */

#include "../Shared.h"
#include "../Bytecode/BytecodeStructures.h"


namespace SymphonyBC {


class BCFileWriter {
public:
	static void writeClass(ClassBC* classBC) {
		string filename = classBC->getName() + CompilerOptions::COMPILED_EXTENSION;
		ofstream fout(filename.c_str(), ios::binary);

		writeStringOnFile(fout, classBC->getDataArea());

#ifdef DEBUG
cout << "=== dataArea size: " << classBC->getDataArea().length() << " ===" << endl << endl;
#endif

		writeIntOnFile(fout, classBC->getLoadedClasses().size());
		BOOST_FOREACH(string loadedClass, classBC->getLoadedClasses()) {
			writeStringOnFile(fout, loadedClass);
		}

#ifdef DEBUG
cout << "=== loaded classes: " << classBC->getLoadedClasses().size() << " ===" << endl;
BOOST_FOREACH(string loadedClass, classBC->getLoadedClasses()) {
	cout << loadedClass << endl;
} cout << endl;
#endif

		writeIntOnFile(fout, classBC->getMembers().size());
		BOOST_FOREACH(MemberBC* memberBC, classBC->getMembers()) {
			writeIntOnFile(fout, memberBC->getType());
			writeStringOnFile(fout, memberBC->getName());
		}

#ifdef DEBUG
cout << "=== members: " << classBC->getMembers().size() << " ===" << endl;
BOOST_FOREACH(MemberBC* memberBC, classBC->getMembers()) {
	cout << memberBC->getType() << " " << memberBC->getName() << endl;
} cout << endl;
#endif

		writeIntOnFile(fout, classBC->getMethods().size());
		BOOST_FOREACH(MethodBC* methodBC, classBC->getMethods()) {
			writeMethod(methodBC, fout);
		}

#ifdef DEBUG
cout << "=== methods: " << classBC->getMethods().size() << " ===" << endl;
BOOST_FOREACH(MethodBC* methodBC, classBC->getMethods()) {
	cout << methodBC->getReturnType() << " " << methodBC->getName() << endl;
} cout << endl;
#endif

		writeIntOnFile(fout, classBC->getSoftlinks().size());
		BOOST_FOREACH(Softlink* softlink, classBC->getSoftlinks()) {
			writeStringOnFile(fout, softlink->refName);
			writeIntOnFile(fout, softlink->objectType);
			writeIntOnFile(fout, softlink->methodIndex);
			writeIntOnFile(fout, softlink->instrPtr);
			writeIntOnFile(fout, softlink->operand);
		}

#ifdef DEBUG
cout << "=== softlinks ===" << endl;
BOOST_FOREACH(Softlink* softlink, classBC->getSoftlinks()) {
	cout << softlink->refName << " " << softlink->instrPtr << endl;
} cout << endl;
#endif
	}

	static void writeMethod(MethodBC* methodBC, ofstream& fout) {
		//int returnType = methodBC->getReturnType();
		//fout.write((char*)&returnType, sizeof(returnType));

		writeStringOnFile(fout, methodBC->getName());

#ifdef DEBUG
cout << methodBC->getName() << endl;
cout << methodBC->getInstructions().size() << endl;
#endif

		writeIntOnFile(fout, methodBC->getInstructions().size());
		BOOST_FOREACH(InstructionBC* instruction, methodBC->getInstructions()) {
			writeShortOnFile(fout, instruction->opcode);
			writeIntOnFile(fout, instruction->op1);
			writeIntOnFile(fout, instruction->op2);
			writeIntOnFile(fout, instruction->op3);

#ifdef DEBUG
cout << instruction->opcode << " " << instruction->op1 << " " << instruction->op2 << " " << instruction->op3 << endl;
#endif
		}

#ifdef DEBUG
cout << endl;
#endif

	}
};


}
